package wsepForum.persistance;

import java.util.Date;
import java.util.Vector;

import wsepForum.common.elements.*;
import wsepForum.common.elements.AForumElement.ForumElementType;
import wsepForum.persistance.exceptions.DataBaseIOException;
import wsepForum.persistance.exceptions.InvalidElementFormatException;
import wsepForum.persistance.exceptions.WrongElementIDException;
import wsepForum.persistance.exceptions.WrongUserNameException;

/**
 * the main interface between the persistence layer and the domain layer. provides the
 * transportation of the AForumElements and users between the 2 layers and provides the
 * domain layer access to the DB.
 * @author Ofir Tam & Ori Ossmy
 */
public interface IPersistentHandler {


	/**
	 * sets the given forum element in the DB under the given parentID.
	 * for Section - parentID is Section.
	 * @param parentID - the place to put the element in the DB
	 * @param element - the element itself (comes with no ID!)
	 * @return double - the ID of the new element
	 * @throws Exception
	 * @preCondition the parentID is legal and represents a topic or section
	 * @preCondition if element has elementID - it exists in the DB, if not - not exists.
	 * @preCondition if parentID represents section - element is message or section or topic (with a 1 message)
	 * 				 if parentID represents topic - element is message. any other possibility is forbidden.
	 * @postCondition is parentID represents section and element is message - a new topic was
	 * 				  created, the given element was inserted to it and the method called again.
	 * @postCondition is element is section or topic - the parent element's headers was updates according to it
	 * @postCondition the DB was updated with the new element and parentElement
	 */
	public int setForumElement(int parentID, ForumElementType parentType, AForumElement element) throws WrongElementIDException, InvalidElementFormatException, DataBaseIOException;




	/**
	 * gets the forum element according to some given header.
	 * @param afhHeader - the element's header required
	 * @return AForumElement - the element itself
	 * @throws Exception
	 * @preCondition the given forumElementID represents and existing element in the DB
	 * @postCondition AForumElement is a legal and exist element in the DB
	 * @postCondition no change in the DB has occurred
	 */
	public AForumElement getForumElement(int forumElementID, ForumElementType type) throws WrongElementIDException, DataBaseIOException;




	/**
	 * checks the given userName and password if exist or not and returns a boolean with the answer
	 * @param strUserName - the user name require to login
	 * @param strPassword - the password of the user require to login
	 * @return boolean - permits the user to login
	 * @throws Exception
	 * @postCondition if boolean=true -> a strUserName with a strPassword exists in the DB
	 * @postCondition if boolean=false -> no strUserName with the given strPasswored exists in the DB
	 * @postCondition no change in the DB has occurred
	 */
	public boolean login(String strUserName, String strPassword) throws WrongUserNameException, DataBaseIOException;




	/**
	 * gets the User object of the given userName (NOTE: the userName is unique!)
	 * @param strUserName - the user name of the required User
	 * @return User - the user object that represents the required user
	 * @throws Exception
	 * @preCondition the given strUserName represents and existing user in the DB
	 * @postCondition User is a legal and exist User in the DB
	 * @postCondition no change in the DB has occurred
	 */
	public User getUser(String strUserName) throws WrongUserNameException, DataBaseIOException;




	/**
	 * sets the User in the DB - used for adding a new user or change password of
	 * existing one - the function gets the User object and according to the
	 * userName - sets the User in the DB
	 * @param user - the User object of the required user
	 * @return boolean - if the action succeeded or not.
	 * @throws Exception
	 * @preCondition user is legal and complete User object
	 * @postCondition a new user was added to the DB represents the given user
	 */
	public boolean setUser(User user) throws DataBaseIOException;




	/**
	 * deletes the given userName from the users that are registered in the system,
	 * according to some given userName. call the DB and remove this userName and it's
	 * associated information from the DB
	 * @param strUserName - the userName of the User to remove
	 * @return boolean - if the action succeeded or not
	 * @throws Exception
	 * @preCondition a user with userName like the given strUserName exists in the DB
	 * @postCondition no user with userName like the given strUserName exists in the DB.
	 */
	public boolean deleteUser(String strUserName) throws WrongUserNameException, DataBaseIOException;



	/**
	 * deletes element from the DB according to a given elementID. if this is a message -
	 * deletes the message from topic. if this is the first message of the topic - deletes
	 * the topic itself from the DB and deletes it's topic header from the parent section,
	 * if this is section - deletes the section header from the parent section's container
	 * @param elementID - the element ID of the element we want to delete
	 * @return AForumElement - the parent Element of the element we deleted
	 * @throws Exception
	 * @preCondition an element with ID like the given elementID exists in the DB
	 * @postCondition no element with ID like the given elementID exists in the DB.
	 * @postCondion the parent of the element was updated in the DB (deleted message or deleted header -
	 * depends on what kind of AForumElement is it.
	 */
	public AForumElement deleteForumElement (int elementID, ForumElementType type) throws WrongElementIDException, DataBaseIOException;

	/**
	 * searches the database for messages written by authorName
	 * @param authorName - the name of the author who wrote the message
	 * @return a vector of messages that fit the query
	 */
	public Vector<SearchResult> searchByAuthor(String authorName) throws Exception;

	/**
	 * searches the database for messages written in a given interval of dates
	 * @param from - the start date
	 * @param to - the end date
	 * @return a vector of messages that fit the query
	 */
	public Vector<SearchResult> searchByDate(Date from, Date to) throws Exception;

	/**
	 * searches the database for messages containing the given sentence
	 * @param sentence - the sentence that should appear in the messages
	 * @return a vector of messages that fit the query
	 */
	public Vector<SearchResult> searchByContent(String sentence) throws Exception;


	/**
	 * init the data if neccessary
	 * @return boolean - if init succeed or not
	 */
	public boolean initDB() throws Exception;

	/**
	 * clear all data (for testing only)
	 */
	public void clearDB() throws Exception;



	/**
	 * closes all open connections/sessions
	 */
	public void close();


	public void logout(String username) throws DataBaseIOException;

	public Vector<String> getUsernameList();

	public double[] getUserCountStatistics(Date date);

	public double[] getMessageCountStatistics(Date date);

	public double[] getUserMessagePerDay(Date date, String userName);


	//public boolean getLock(String lock) throws Exception;
	//public void releaseLock(String lock) throws Exception;

}
